package com.example.module_publish.rtmp;

import static android.hardware.Camera.Parameters.FOCUS_MODE_AUTO;
import static android.hardware.Camera.Parameters.PREVIEW_FPS_MAX_INDEX;
import static android.hardware.Camera.Parameters.PREVIEW_FPS_MIN_INDEX;

import android.app.Activity;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.util.Log;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * @author yaotianxue
 * @description
 * @date 2025/3/7
 */
public class VideoHelper {
    private static final String TAG = "VideoGatherer";

    private Config config;
    private Camera mCamera;
    public Camera.Size previewSize;


    private LinkedBlockingQueue<byte[]> mQueue = new LinkedBlockingQueue<>();
    private Thread workThread;
    private boolean loop;
    public static VideoHelper newInstance(Config config) {
        return new VideoHelper(config);
    }
    private VideoHelper(Config config) {
        this.config = config;
    }
    private Callback mCallback;
    public interface Callback {
        void onReceive(byte[] data);
    }

    public void setCallback(Callback callback) {
        this.mCallback = callback;
    }


    /**
     * 初始化Camera
     */
    public void initCamera (SurfaceTexture surfaceTexture) {
        // first release
        release();

        openCamera();
        setCameraParameters();
//        setCameraDisplayOrientation(act, Camera.CameraInfo.CAMERA_FACING_BACK, mCamera);
        try {
            mCamera.setPreviewTexture(surfaceTexture);
        } catch (IOException e) {
            e.printStackTrace();
        }

        mCamera.setPreviewCallbackWithBuffer(getPreviewCallback());
        mCamera.addCallbackBuffer(new byte[calculateFrameSize(ImageFormat.NV21)]);
        mCamera.startPreview();

        mCamera.cancelAutoFocus();

        //开启子线程
        initWorkThread();
        loop = true;
        workThread.start();

    }
    private void initWorkThread() {
        workThread = new Thread() {
            private long preTime;
            //YUV420
            byte[] dstByte = new byte[calculateFrameSize(ImageFormat.NV21)];

            @Override
            public void run() {
                while (loop && !Thread.interrupted()) {
                    try {
                        byte[] bytes = mQueue.take();
                        // 处理
                        Yuv420Util.Nv21ToI420(bytes, dstByte, previewSize.width,
                                previewSize.height);

                        if (mCallback != null) {
                            mCallback.onReceive(dstByte);
                        }
                        //处理完成之后调用 addCallbackBuffer()
                        if (preTime != 0) {
                            // 延时
                            int shouldDelay = (int) (1000.0 / config.fps);
                            int realDelay = (int) (System.currentTimeMillis() - preTime);
                            int delta = shouldDelay - realDelay;
                            if (delta > 0) {
                                sleep(delta);
                            }
                        }
                        mCamera.addCallbackBuffer(bytes);
                        preTime = System.currentTimeMillis();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        break;
                    }
                }
            }
        };

    }

    /**
     * 数据返回接口 美白等特效处理位置
     *
     * @return
     */
    public Camera.PreviewCallback getPreviewCallback() {
        return new Camera.PreviewCallback() {
            //            byte[] dstByte = new byte[calculateFrameSize(ImageFormat.NV21)];
            @Override
            public void onPreviewFrame(byte[] data, final Camera camera) {
                Log.d(TAG, "onPreviewFrame: "+data);
                if (data != null) {
                    try {
                        mQueue.put(data);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    camera.addCallbackBuffer(new byte[calculateFrameSize(ImageFormat.NV21)]);
                }
            }
        };
    }

    public void release() {
        releaseCamera();
        if (workThread != null) {
            workThread.interrupt();
            loop = false;
        }
    }
    /**
     * 释放相机
     */
    public void releaseCamera() {
        if (mCamera != null) {
            mCamera.setPreviewCallbackWithBuffer(null);
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }
    /**
     * 打开摄像头
     */
    private void openCamera() {
        if (mCamera == null) {
            try {
                mCamera = Camera.open();
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("打开摄像头失败", e);
            }
        }
    }
    /**
     * 设置相机参数信息
     */
    private void setCameraParameters() {
        try {
            Camera.Parameters parameters = mCamera.getParameters();
            List<Camera.Size> supportedPreviewSizes = parameters.getSupportedPreviewSizes();
            for (Camera.Size size : supportedPreviewSizes
            ) {
                if (size.width >= config.minWidth && size.width <= config.maxWidth) {
                    previewSize = size;
                    Log.i(TAG, String.format("find preview size width=%d,height=%d", previewSize.width,
                            previewSize.height));
                    break;
                }
            }


            int[] destRange = {config.fps * 1000, config.fps * 1000};
            List<int[]> supportedPreviewFpsRange = parameters.getSupportedPreviewFpsRange();
            for (int[] range : supportedPreviewFpsRange
            ) {
                if (range[PREVIEW_FPS_MAX_INDEX] >= config.fps * 1000) {
                    destRange = range;
                    Log.d(TAG, String.format("find fps range :%s", Arrays.toString(destRange)));
                    break;
                }
            }

            if (previewSize == null) {
                throw new RuntimeException("find previewSize error");
            }

//            parameters.setPictureSize(previewSize.width, previewSize.height);
            parameters.setPreviewSize(previewSize.width, previewSize.height);
            Log.d("123",String.format("Preview Size -> width = %d, height = %d", previewSize.width, previewSize.height));
            parameters.setPreviewFpsRange(destRange[PREVIEW_FPS_MIN_INDEX],
                    destRange[PREVIEW_FPS_MAX_INDEX]);

            List<String> supportedFocusModes = parameters.getSupportedFocusModes();
            for (int i = 0; null != supportedFocusModes && i < supportedFocusModes.size(); i++) {
                if (FOCUS_MODE_AUTO.equals(supportedFocusModes.get(i))) {
                    parameters.setFocusMode(FOCUS_MODE_AUTO);
                    break;
                }
            }
            parameters.setPreviewFormat(ImageFormat.NV21);
            parameters.setFocusMode(FOCUS_MODE_AUTO);
            mCamera.setParameters(parameters);
            mCamera.autoFocus(new Camera.AutoFocusCallback() {
                @Override
                public void onAutoFocus(boolean b, Camera camera) {
                    if(b){
                        mCamera.cancelAutoFocus();
                        Camera.Parameters parameters1 = mCamera.getParameters();
                        parameters1.setFocusMode(FOCUS_MODE_AUTO);
                        mCamera.setParameters(parameters1);

                    }
                }
            });
        }catch (Exception e) {
            Log.e("123","setCameraParameters:"+e.getMessage());
        }
    }
    private int calculateFrameSize(int format) {
        return previewSize.width * previewSize.height * ImageFormat.getBitsPerPixel(format) / 8;
    }

}
